package com.retail.lottery.colalottery.utils;

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.nio.charset.StandardCharsets;
import java.util.Base64;

/**
 * Aes加解密操作类
 *
 * @author zy
 */
public class AesUtil {

    private static final String AES_ALGORITHM = "AES";
    private static final String AES_CBC_PKCS5_PADDING = "AES/CBC/PKCS5Padding";

    /**
     * AES 加密（返回 Base64 编码结果）
     *
     * @param data 待加密数据
     * @param key  密钥（16/24/32字节）
     * @param iv   初始化向量（16字节）
     * @return Base64 编码的加密结果
     */
    public static String encryptBase64(String data, String key, String iv) {
        try {
            byte[] encryptedBytes = encrypt(data.getBytes(StandardCharsets.UTF_8),
                    key.getBytes(StandardCharsets.UTF_8),
                    iv.getBytes(StandardCharsets.UTF_8));
            return Base64.getEncoder().encodeToString(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException("AES encryption failed", e);
        }
    }

    /**
     * AES 解密（传入 Base64 编码数据）
     *
     * @param base64Data Base64 编码的加密数据
     * @param key       密钥（16/24/32字节）
     * @param iv        初始化向量（16字节）
     * @return 解密后的原始字符串
     */
    public static String decryptBase64(String base64Data, String key, String iv) {
        try {
            byte[] encryptedBytes = Base64.getDecoder().decode(base64Data);
            byte[] decryptedBytes = decrypt(encryptedBytes,
                    key.getBytes(StandardCharsets.UTF_8),
                    iv.getBytes(StandardCharsets.UTF_8));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("AES decryption failed", e);
        }
    }

    /**
     * AES 加密（返回 Hex 编码结果）
     *
     * @param data 待加密数据
     * @param key  密钥（16/24/32字节）
     * @param iv   初始化向量（16字节）
     * @return Hex 编码的加密结果
     */
    public static String encryptHex(String data, String key, String iv) {
        try {
            byte[] encryptedBytes = encrypt(data.getBytes(StandardCharsets.UTF_8),
                    key.getBytes(StandardCharsets.UTF_8),
                    iv.getBytes(StandardCharsets.UTF_8));
            return bytesToHex(encryptedBytes);
        } catch (Exception e) {
            throw new RuntimeException("AES encryption failed", e);
        }
    }

    /**
     * AES 解密（传入 Hex 编码数据）
     *
     * @param hexData Hex 编码的加密数据
     * @param key     密钥（16/24/32字节）
     * @param iv      初始化向量（16字节）
     * @return 解密后的原始字符串
     */
    public static String decryptHex(String hexData, String key, String iv) {
        try {
            byte[] encryptedBytes = hexToBytes(hexData);
            byte[] decryptedBytes = decrypt(encryptedBytes,
                    key.getBytes(StandardCharsets.UTF_8),
                    iv.getBytes(StandardCharsets.UTF_8));
            return new String(decryptedBytes, StandardCharsets.UTF_8);
        } catch (Exception e) {
            throw new RuntimeException("AES decryption failed", e);
        }
    }

    // 加密方法
    private static byte[] encrypt(byte[] data, byte[] key, byte[] iv) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey, ivParameterSpec);
        return cipher.doFinal(data);
    }

    // 解密方法
    private static byte[] decrypt(byte[] encryptedData, byte[] key, byte[] iv) throws Exception {
        SecretKeySpec secretKey = new SecretKeySpec(key, AES_ALGORITHM);
        IvParameterSpec ivParameterSpec = new IvParameterSpec(iv);
        Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5_PADDING);
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ivParameterSpec);
        return cipher.doFinal(encryptedData);
    }

    // Byte[] 转 Hex
    private static String bytesToHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        for (byte b : bytes) {
            sb.append(String.format("%02x", b));
        }
        return sb.toString();
    }

    // Hex 转 Byte[]
    private static byte[] hexToBytes(String hex) {
        int len = hex.length();
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(hex.charAt(i), 16) << 4)
                    + Character.digit(hex.charAt(i + 1), 16));
        }
        return data;
    }

    public static void main(String[] args) {
        String key = "1234567890abcdef"; // 16字节密钥
        String iv = "abcdef1234567890";  // 16字节IV
        String data = "Hello, AES!";

        // Base64 测试
        String encryptedBase64 = encryptBase64(data, key, iv);
        System.out.println("Encrypted (Base64): " + encryptedBase64);
        String decryptedBase64 = decryptBase64(encryptedBase64, key, iv);
        System.out.println("Decrypted (Base64): " + decryptedBase64);

        // Hex 测试
        String encryptedHex = encryptHex(data, key, iv);
        System.out.println("Encrypted (Hex): " + encryptedHex);
        String decryptedHex = decryptHex(encryptedHex, key, iv);
        System.out.println("Decrypted (Hex): " + decryptedHex);
    }
}